﻿using AiQiuQuan.Sport.Core;
using AiQiuQuan.Sport.Core.Tool;
using AiQiuQuan.Sport.Model.Enums;
using AiQiuQuan.Sport.Model.Models;
using AiQiuQuan.Sport.WebApi.Entities;
using Microsoft.EntityFrameworkCore;
using System.Text.Json;

namespace AiQiuQuan.Sport.WebApi.Services.Impl
{
    /// <summary>
    /// 活动、比赛、约球支付退款逻辑
    /// </summary>
    public partial class PayService
    {
        /// <summary>
        /// 活动、约球、比赛订单逻辑
        /// </summary>
        private async Task<UnaryResult<PayResultDto>> PayGameOrderAsync(PayRequestDto request, PayOrderInnerInfo payInner, PayResultDto payResult, BaseUser user)
        {
            var gameOrder = await _gameOrderRepository.FirstOrDefaultAsync(m => m.ID == request.OrderId && m.State == GameOrderStateEnum.NotPay);
            if (gameOrder == null)
            {
                return UnaryResult.From(10, payResult, $"未查询到业务订单：{request.OrderId}");
            }

            gameOrder.PayType = request.PayType;
            await _gameOrderRepository.UpdateAsync(gameOrder);

            payInner.OrderNo = gameOrder.OrderNo;
            payInner.ProductName = gameOrder.Name;
            payInner.ProductDescription = gameOrder.Remark;
            payInner.OrderAmount = gameOrder.OrderAmount;
            payInner.DiscountAmount = gameOrder.BonusAmount + gameOrder.CouponAmount;
            payInner.PayAmount = gameOrder.PayAmount;
            payInner.PayState = PayOrderStateEnum.NotPay;
            payInner.PayRemark = $"{DateTimeOffset.Now},{gameOrder.Name} 报名";
            payInner.IsCompatibleVenueOrder = false;
            payInner.Payer = user.U_OpenId;

            return UnaryResult.Succeed(payResult);
        }

        /// <summary>
        /// 活动、比赛、约球订单退款逻辑
        /// </summary>
        private async Task<UnaryResult<RefundResultDto>> ExecuteGameOrderRefundAsync(RefundRequestDto request, PayOrder payOrder, RefundResultDto result)
        {
            var gameOrder = await _gameOrderRepository.FirstOrDefaultAsync(m => m.ID == request.OrderId);
            if (gameOrder == null)
            {
                result.Msg = "未查询到业务订单";
                return UnaryResult.From(10, result, result.Msg);
            }

            if (gameOrder.State == GameOrderStateEnum.Cancel)
            {
                result.Msg = "订单已取消";
                return UnaryResult.From(10, result, result.Msg);
            }

            if (gameOrder.State == GameOrderStateEnum.Completed || gameOrder.State == GameOrderStateEnum.Refunded)
            {
                result.Msg = "订单已完成，无法执行退款";
                return UnaryResult.From(10, result, result.Msg);
            }

            //分具体业务进行相关判断及赋值,未支付取消业务逻辑也在此实现
            //实际待取消参赛人员ID
            var cancelinglUserIdList = new List<Guid>();
            switch (gameOrder.BusinessType)
            {
                case BusinessTypeEnum.Activity:
                    var activityResult = await ExecuteActivityRefundAsync(request, gameOrder, result, cancelinglUserIdList);
                    if (activityResult.Code != 0 || activityResult.Data.IsSuccess)
                    {
                        return activityResult;
                    }

                    break;
                case BusinessTypeEnum.Ball:
                    var ballResult = await ExecuteBallRefundAsync(request, gameOrder, result, cancelinglUserIdList);
                    if (ballResult.Code != 0 || ballResult.Data.IsSuccess)
                    {
                        return ballResult;
                    }

                    break;
                case BusinessTypeEnum.Game:
                    var gameResult = await ExecuteGameRefundAsync(request, gameOrder, result);
                    if (gameResult.Code != 0 || gameResult.Data.IsSuccess)
                    {
                        return gameResult;
                    }

                    break;
            }

            if (request.CancelType != OrderCancelTypeEnum.User)
            {
                result.ApplyAmount = request.ApplyAmount;
                result.RefundAmount = request.ApplyAmount;
                Enum.TryParse<GameJoinStateEnum>(request.AttachData, out var joinState);
                if (request.BusinessType == BusinessTypeEnum.Game && GameJoinStateEnum.Refused == joinState)
                {
                    result.ApplyAmount = gameOrder.PayAmount;
                    result.RefundAmount = gameOrder.PayAmount;
                }
                else if (request.BusinessType == BusinessTypeEnum.Ball)
                {
                    var ballRefundAttach = JsonSerializer.Deserialize<BallRefundAttachData>(request.AttachData);
                    if (ballRefundAttach.JoinState == GameJoinStateEnum.Refused)
                    {
                        result.ApplyAmount = gameOrder.Price * ballRefundAttach.UserIdList.Count;
                        result.RefundAmount = gameOrder.Price * ballRefundAttach.UserIdList.Count;
                    }
                }
            }
            else
            {
                if (gameOrder.BusinessType == BusinessTypeEnum.Activity || gameOrder.BusinessType == BusinessTypeEnum.Ball)
                {
                    result.ApplyAmount = gameOrder.Price * cancelinglUserIdList.Count;
                    result.RefundAmount = gameOrder.Price * cancelinglUserIdList.Count;
                }
                else
                {
                    result.ApplyAmount = gameOrder.PayAmount;
                    result.RefundAmount = gameOrder.PayAmount;
                }
            }

            if (result.ApplyAmount <= 0)
            {
                result.Msg = "退款金额小于等于0";
                return UnaryResult.From(10, result, result.Msg);
            }

            if (payOrder.PayAmount < payOrder.RefundAmount + result.ApplyAmount)
            {
                result.Msg = "订单未退金额不足";
                return UnaryResult.From(10, result, result.Msg);
            }

            if (gameOrder.BusinessType == BusinessTypeEnum.Activity && cancelinglUserIdList.Any())
            {
                result.ExtJson = JsonTool.JsonSerialize(cancelinglUserIdList);
            }

            return UnaryResult.Succeed(result);
        }

        /// <summary>
        /// 活动订单相关退款逻辑,赋值未取消人员ID
        /// </summary>
        private async Task<UnaryResult<RefundResultDto>> ExecuteActivityRefundAsync(RefundRequestDto request, GameOrder gameOrder, RefundResultDto result, List<Guid> cancelinglUserIdList)
        {
            Activity activity = null;
            var requestUserIdList = GetRefundUserIdList(request.AttachData);
            if (!requestUserIdList.Any())
            {
                result.Msg = "待取消参赛人员必选";
                return UnaryResult.From(10, result, result.Msg);
            }

            var activityUserList = await _activityUserRepository.AsNoTracking().Where(m => m.GameOrderId == request.OrderId).ToListAsync();
            var cancelUserIdList = activityUserList.Where(m => m.JoinState == GameJoinStateEnum.Cancel || m.JoinState == GameJoinStateEnum.Refused).Select(m => m.UserId).ToList();
            var notCancelUserIdList = activityUserList.Where(m => !cancelUserIdList.Contains(m.UserId)).Select(m => m.UserId).ToList();
            //未付款取消订单，直接更改相关业务状态，返回
            if (gameOrder.State == GameOrderStateEnum.NotPay)
            {
                await using (var redlock = await _distributedLockFactory.CreateLockAsync(gameOrder.BusinessId.ToString("N"), TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(1)))
                {
                    if (!redlock.IsAcquired)
                    {
                        result.Msg = "退款通道拥堵，稍后重试";
                        return UnaryResult.From(10, result, result.Msg);
                    }

                    gameOrder.State = GameOrderStateEnum.Cancel;
                    gameOrder.CancelCount = gameOrder.JoinCount;
                    gameOrder.CancelTime = DateTimeOffset.Now;
                    activity = await _activityRepository.FirstOrDefaultAsync(m => m.ID == gameOrder.BusinessId);
                    if (activity != null)
                    {
                        activity.TotalCount = activity.TotalCount - gameOrder.JoinCount > 0 ? activity.TotalCount - gameOrder.JoinCount : 0;
                    }

                    var activityUserBuilder = await _activityUserRepository.UpdatePartialAsync();
                    activityUserBuilder = activityUserBuilder.Set(m => m.PayState, PayOrderStateEnum.Canceled)
                        .Set(m => m.JoinState, GameJoinStateEnum.Cancel).Where(m => m.GameOrderId == gameOrder.ID);

                    using (var uow = _unitOfWorkManager.Begin())
                    {
                        await _activityRepository.UpdateAsync(activity);
                        await _gameOrderRepository.UpdateAsync(gameOrder);
                        await activityUserBuilder.ExecuteAsync();
                        await uow.CompleteAsync();
                    }

                    result.IsSuccess = true;
                    result.Msg = "未支付取消订单成功";
                    return UnaryResult.Succeed(result);
                }
            }

            activity = await _activityRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == gameOrder.BusinessId);
            if (request.CancelType == OrderCancelTypeEnum.User && (activity.State == GameStateEnum.Processing || activity.State == GameStateEnum.Finished))
            {
                result.Msg = "活动进行中或已结束，不能退款";
                return UnaryResult.From(10, result, result.Msg);
            }

            //判断待取消人员是否重复
            if (requestUserIdList.Any())
            {
                if (requestUserIdList.Any(m => cancelUserIdList.Contains(m)))
                {
                    result.Msg = "参赛用户重复取消";
                    return UnaryResult.From(10, result, result.Msg);
                }

                cancelinglUserIdList.AddRange(requestUserIdList);
            }
            else
            {
                cancelinglUserIdList.AddRange(notCancelUserIdList);
            }

            return UnaryResult.Succeed(result);
        }

        /// <summary>
        /// 比赛订单相关退款逻辑
        /// </summary>
        private async Task<UnaryResult<RefundResultDto>> ExecuteGameRefundAsync(RefundRequestDto request, GameOrder gameOrder, RefundResultDto result)
        {
            //未付款取消订单，直接更改相关业务状态，返回
            if (gameOrder.State == GameOrderStateEnum.NotPay)
            {
                await using (var redlock = await _distributedLockFactory.CreateLockAsync(gameOrder.BusinessId.ToString("N"), TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(1)))
                {
                    if (!redlock.IsAcquired)
                    {
                        result.Msg = "退款通道拥堵，稍后重试";
                        return UnaryResult.From(10, result, result.Msg);
                    }

                    gameOrder.State = GameOrderStateEnum.Cancel;
                    gameOrder.CancelCount = gameOrder.JoinCount;
                    gameOrder.CancelTime = DateTimeOffset.Now;

                    Enum.TryParse<GameJoinStateEnum>(request.AttachData, out var joinState);
                    joinState = joinState == GameJoinStateEnum.Refused ? GameJoinStateEnum.Refused : GameJoinStateEnum.Cancel;
                    var gameTeamBuilder = await _gameTeamRepository.UpdatePartialAsync();
                    gameTeamBuilder = gameTeamBuilder.Set(m => m.PayState, PayOrderStateEnum.Canceled)
                        .Set(m => m.JoinState, joinState).Where(m => m.GameOrderId == gameOrder.ID);

                    using (var uow = _unitOfWorkManager.Begin())
                    {
                        await _gameOrderRepository.UpdateAsync(gameOrder);
                        await gameTeamBuilder.ExecuteAsync();
                        await uow.CompleteAsync();
                    }

                    result.IsSuccess = true;
                    result.Msg = "未支付取消订单成功";
                    return UnaryResult.Succeed(result);
                }
            }

            var game = await _gameRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == gameOrder.BusinessId);
            if (request.CancelType == OrderCancelTypeEnum.User && (game.State == GameStateEnum.Processing || game.State == GameStateEnum.Finished))
            {
                result.Msg = "比赛进行中或已结束，不能退款";
                return UnaryResult.From(10, result, result.Msg);
            }

            return UnaryResult.Succeed(result);
        }

        /// <summary>
        /// 约球订单相关退款逻辑,赋值未取消人员ID
        /// </summary>
        private async Task<UnaryResult<RefundResultDto>> ExecuteBallRefundAsync(RefundRequestDto request, GameOrder gameOrder, RefundResultDto result, List<Guid> cancelinglUserIdList)
        {
            var ballRefundAttach = JsonSerializer.Deserialize<BallRefundAttachData>(request.AttachData);
            if (ballRefundAttach == null || ballRefundAttach.UserIdList == null || !ballRefundAttach.UserIdList.Any())
            {
                result.Msg = "待取消参赛人员必选";
                return UnaryResult.From(10, result, result.Msg);
            }

            if (ballRefundAttach.JoinState != GameJoinStateEnum.Cancel && ballRefundAttach.JoinState != GameJoinStateEnum.Refused)
            {
                result.Msg = "报名状态只能为取消或拒绝";
                return UnaryResult.From(10, result, result.Msg);
            }

            var ball = await _ballRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == gameOrder.BusinessId);
            if (!request.IsPlatform.GetValueOrDefault())
            {
                if (ballRefundAttach.JoinState == GameJoinStateEnum.Refused && ball.UserId != _currentInfo.UserId)
                {
                    result.Msg = "非约球创建者";
                    return UnaryResult.From(10, result, result.Msg);
                }

                if (ballRefundAttach.JoinState == GameJoinStateEnum.Cancel && gameOrder.UserId != _currentInfo.UserId)
                {
                    result.Msg = "非约球报名者";
                    return UnaryResult.From(10, result, result.Msg);
                }
            }

            var ballUserList = await _ballUserRepository.AsNoTracking().Where(m => m.GameOrderId == request.OrderId).ToListAsync();
            var cancelUserIdList = ballUserList.Where(m => m.JoinState == GameJoinStateEnum.Cancel || m.JoinState == GameJoinStateEnum.Refused).Select(m => m.UserId).ToList();
            var notCancelUserIdList = ballUserList.Where(m => !cancelUserIdList.Contains(m.UserId)).Select(m => m.UserId).ToList();
            //未付款取消订单，直接更改相关业务状态，返回
            if (gameOrder.State == GameOrderStateEnum.NotPay)
            {
                await using (var redlock = await _distributedLockFactory.CreateLockAsync(gameOrder.BusinessId.ToString("N"), TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(1)))
                {
                    if (!redlock.IsAcquired)
                    {
                        result.Msg = "退款通道拥堵，稍后重试";
                        return UnaryResult.From(10, result, result.Msg);
                    }

                    gameOrder.State = GameOrderStateEnum.Cancel;
                    gameOrder.CancelCount = gameOrder.JoinCount;
                    gameOrder.CancelTime = DateTimeOffset.Now;

                    var ballUserBuilder = await _ballUserRepository.UpdatePartialAsync();
                    ballUserBuilder = ballUserBuilder.Set(m => m.PayState, PayOrderStateEnum.Canceled)
                        .Set(m => m.JoinState, ballRefundAttach.JoinState).Where(m => m.GameOrderId == gameOrder.ID);

                    using (var uow = _unitOfWorkManager.Begin())
                    {
                        await _gameOrderRepository.UpdateAsync(gameOrder);
                        await ballUserBuilder.ExecuteAsync();
                        await uow.CompleteAsync();
                    }

                    result.IsSuccess = true;
                    result.Msg = "未支付取消订单成功";
                    return UnaryResult.Succeed(result);
                }
            }

            if (request.CancelType == OrderCancelTypeEnum.User && (ball.State == GameStateEnum.Processing || ball.State == GameStateEnum.Finished))
            {
                result.Msg = "活动进行中或已结束，不能退款";
                return UnaryResult.From(10, result, result.Msg);
            }

            //判断待取消人员是否重复
            if (ballRefundAttach.UserIdList.Any(m => cancelUserIdList.Contains(m)))
            {
                result.Msg = "参赛用户重复拒绝或取消";
                return UnaryResult.From(10, result, result.Msg);
            }

            cancelinglUserIdList.AddRange(ballRefundAttach.UserIdList);
            return UnaryResult.Succeed(result);
        }
    }
}
